package me.nibo.tree.utils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import me.nibo.tree.R;
import me.nibo.tree.utils.annotation.TreeNodeId;
import me.nibo.tree.utils.annotation.TreeNodeLabel;
import me.nibo.tree.utils.annotation.TreeNodePid;

/**
 * @author nibo
 */
public class TreeHelper {

    /**
     * 将业务数据转换为Tree Node数据
     *
     * @param datas 业务数据集合
     * @param <T>   泛型
     * @return Tree Node数据集合
     * @throws IllegalAccessException
     */
    private static <T> List<Node> convertDatas2Nodes(List<T> datas) throws IllegalAccessException {
        if (null == datas || datas.size() == 0) {
            return new ArrayList<>(1);
        }
        List<Node> nodeList = new ArrayList<>(datas.size());
        Node node;
        String id = "";
        String pid = "";
        String label = "";
        for (T t : datas) {
            Class cls = t.getClass();
            Field[] fields = cls.getDeclaredFields();
            for (Field f : fields) {
                f.setAccessible(true);
                if (f.getAnnotation(TreeNodeId.class) != null) {
                    id = (String) f.get(t);
                }
                if (f.getAnnotation(TreeNodePid.class) != null) {
                    pid = (String) f.get(t);
                }
                if (f.getAnnotation(TreeNodeLabel.class) != null) {
                    label = (String) f.get(t);
                }
            }
            node = new Node(id, pid, label);
            nodeList.add(node);
        }
        // 设置节点关系
        setNodeRelation(nodeList);

        for (Node n : nodeList) {
            setNodeIcon(n);
        }

        return nodeList;
    }

    /**
     * 获取排序后的节点数据集合
     *
     * @param datas              业务数据集合
     * @param defaultExpandLevel 默认展开层级
     * @param <T>                泛型
     * @return 排序后的节点数据集合
     * @throws IllegalAccessException
     */
    public static <T> List<Node> getSortedNode(List<T> datas,
                                               int defaultExpandLevel)
            throws IllegalAccessException {

        List<Node> results = new ArrayList<>();
        List<Node> nodes = convertDatas2Nodes(datas);
        List<Node> rootNodes = getRootNodes(nodes);

        for (Node rootNode : rootNodes) {
            addNodes(results, rootNode, defaultExpandLevel, 1);
        }
        return results;
    }

    /**
     * 过滤可见的节点
     * @param nodes 节点数据集合
     * @return 可见节点
     */
    public static List<Node> filterVisibleNode(List<Node> nodes) {
        List<Node> results = new ArrayList<>();
        for (Node node : nodes) {
            if (node.isRoot() || node.getParent().isExpand()) {
                setNodeIcon(node);
                results.add(node);
            }
        }
        return results;
    }

    /**
     * 添加所有节点下的子节点
     *
     * @param results            结果数据集合
     * @param node               节点对象
     * @param defaultExpandLevel 默认展开层级
     * @param currentLevel       当前层级
     */
    private static void addNodes(List<Node> results, Node node,
                                 int defaultExpandLevel, int currentLevel) {
        results.add(node);
        if (defaultExpandLevel >= currentLevel) {
            node.setExpand(true);
        }
        // 当前节点已经是叶子节点，即它下面再没有子节点
        if (node.isLeaf()) {
            return;
        }
        // 循环当前节点下的子节点，并递归调用
        for (int i = 0; i < node.getChildNodes().size(); i++) {
            addNodes(results, node.getChildNodes().get(i), defaultExpandLevel, currentLevel + 1);
        }
    }

    /**
     * 获取所有的根节点
     *
     * @param nodes 节点数据集合
     * @return 根节点数据集合
     */
    private static List<Node> getRootNodes(List<Node> nodes) {
        List<Node> rootNodes = new ArrayList<>();
        for (Node node : nodes) {
            if (node.isRoot()) {
                rootNodes.add(node);
            }
        }
        return rootNodes;
    }

    /**
     * 设置节点图标
     *
     * @param n 节点对象
     */
    private static void setNodeIcon(Node n) {
        if (n.getChildNodes().size() > 0 && n.isExpand()) {
            n.setIcon(R.drawable.tree_ex);
        } else if (n.getChildNodes().size() > 0 && !n.isExpand()) {
            n.setIcon(R.drawable.tree_ec);
        } else {
            n.setIcon(-1);
        }
    }

    /**
     * 设置节点关系
     *
     * @param nodeList 节点数据集合
     */
    private static void setNodeRelation(List<Node> nodeList) {
        for (int i = 0; i < nodeList.size(); i++) {
            Node n = nodeList.get(i);
            for (int j = i + 1; j < nodeList.size(); j++) {
                Node m = nodeList.get(j);
                if (m.getPid().equals(n.getId())) {
                    n.getChildNodes().add(m);
                    m.setParent(n);
                } else if (m.getId().equals(n.getPid())) {
                    m.getChildNodes().add(n);
                    n.setParent(m);
                }
            }
        }
    }
}
